#ifndef __WEB_SERVER_H__
#define __WEB_SERVER_H__

#include "../Epoll/epoll.h"
#include "../Log/Log.h"
#include "../Socket/Sock.h"
#include "../Mysql/sqlconpool.h"
#include "../ThreadPool/threadpool.h"
#include "../http/httpconn.h"
#include "../timer/heaptimer.h"

#include <sys/fcntl.h> // fcntl
#include <cstring>

class WebServer
{
public:
    WebServer(
        int port, int trigMode, int timeoutMS, bool OptLinger,
        int sqlPort, const char *sqlUser, const char *sqlPwd,
        const char *dbName, int connPoolNum, int threadNum,
        bool openLog, int logLevel, int logQueSize);
    ~WebServer();
    
    void start();
private:
    bool InitSocket_();
    static int SetFdNonblock(int fd); // 设置文件描述符非阻塞
    void InitEventMode_(int trigMode);

    void AddClient_(int fd, sockaddr_in addr);

    void DealListen_();
    void DealWrite_(HttpConn *client);
    void DealRead_(HttpConn *client);

    void SendError_(int fd, const char *info);
    void ExtentTime_(HttpConn *client);
    void CloseConn_(HttpConn *client);

    void OnRead_(HttpConn *client);
    void OnWrite_(HttpConn *client);
    void OnProcess(HttpConn *client);

    static const int MAX_FD = 65536;    // 最大的文件描述符的个数


private:
    int port_;        // 端口
    bool openLinger_; // 是否打开优雅关闭
    int timeoutMS_;   /* 毫秒MS */
    bool isClose_;    // 是否关闭
    int listenFd_;    // 监听的文件描述符
    char *srcDir_;    // 资源的目录

    uint32_t listenEvent_; // 监听的文件描述符的事件
    uint32_t connEvent_;   // 连接的文件描述符的事件

    std::unique_ptr<HeapTimer> timer_;        // 定时器
    std::unique_ptr<ThreadPool> threadpool_;  // 线程池
    std::unique_ptr<Epoll> epoller_;          // epoll对象
    std::unordered_map<int, HttpConn> users_; // 保存的是客户端连接的信息
};

#endif